package net.yc.web.imalachat.push.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

/**
 * Created by qiujuer
 * on 2017/2/17.
 *
 */
public class Hib {
    // 全局SessionFactory
    private static SessionFactory sessionFactory;

    static {
        // 静态初始化sessionFactory
        init();
    }

    private static void init() {
        // 从hibernate.cfg.xml文件初始化
        final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                .configure() // configures settings from hibernate.cfg.xml
                .build();
        try {
            // build 一个sessionFactory
            sessionFactory = new MetadataSources(registry)
                    .buildMetadata()
                    .buildSessionFactory();
        } catch (Exception e) {
            e.printStackTrace();
            // 错误则打印输出，并销毁
            StandardServiceRegistryBuilder.destroy(registry);
        }
    }

    /**
     * 获取全局的SessionFactory
     *
     * @return SessionFactory
     */
    public static SessionFactory sessionFactory() {
        return sessionFactory;
    }

    /**
     * 从SessionFactory中得到一个Session会话
     *
     * @return Session
     */
    public static Session session() {
        return sessionFactory.getCurrentSession();
    }

    /**
     * 关闭sessionFactory
     */
    public static void closeFactory() {
        if (sessionFactory != null) {
            sessionFactory.close();
        }
    }

    /**
     * 用于用户实际操作的一个接口，返回一个T
     * @param <T>
     */
    public interface Query<T> {
        T query(Session session);
    }

    /**
     * 无返回值
     */
    public interface QueryOnly {
        void query(Session session);
    }

    /**
     * 简化Session事务操作的一个工具方法
     * @param query
     */
    public static void queryOnly (QueryOnly query) {
        // 重新开始一个session，为了避免重复
        Session session = sessionFactory.openSession();
        // 开启事务
        final Transaction transaction = session.beginTransaction();

        try {
            // 调用传递过来的接口，并调用接口的方法把Session传递进去
            query.query(session);
            // 提交
            transaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
            // 回滚
            try {
                transaction.rollback();
            } catch (RuntimeException exception) {
                exception.printStackTrace();
            }

        } finally {
            // 无论是成功还是失败，都需要去关闭我们的session
            session.close();
        }
    }

    /**
     * 简化Session操作的一个工具方法
     * @param query
     * @param <T>
     * @return
     */
    public static<T> T query(Query<T> query) {
        // 重新开始一个Session
        Session session = sessionFactory().openSession();
        // 开启一个事务
        final Transaction transaction = session.beginTransaction();

        T t = null;

        try {
            t = query.query(session);
            // 提交
            transaction.commit();
        } catch(Exception e) {
            e.printStackTrace();
            // 回滚
            try {
                transaction.rollback();
            } catch (RuntimeException exception) {
                exception.printStackTrace();
            }
        } finally {
            session.close();
        }
        return t;
    }
}
